package xyz.riceball.security.authentication;

import lombok.Getter;
import lombok.Setter;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import xyz.riceball.security.common.SecurityConstant;
import xyz.riceball.usercore.entity.dto.LoginDTO;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * <p>
 * 核心拦截器Filter
 * 身份验证
 * </p>
 *
 * @author xiaovcloud
 * @since 2022/4/25 00:18
 */
@Getter
@Setter
public class RiceBallAuthLoginFilter extends AbstractAuthenticationProcessingFilter {

    private boolean postOnly = true;

    HttpMessageConverter<LoginDTO> httpMessageConverter;

    public RiceBallAuthLoginFilter(HttpMessageConverter<LoginDTO> httpMessageConverter) {
        super(new AntPathRequestMatcher(SecurityConstant.LOGIN_URL, HttpMethod.POST.toString()));
        this.httpMessageConverter = httpMessageConverter;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException {
        if (postOnly && !HttpMethod.POST.matches(request.getMethod())) {
            throw new AuthenticationServiceException("请求类型不支持: " + request.getMethod());
        }
        ServletServerHttpRequest servletServerHttpRequest = new ServletServerHttpRequest(request);
        MediaType contentType = servletServerHttpRequest.getHeaders().getContentType();
        if (contentType != null && !contentType.includes(MediaType.APPLICATION_JSON)) {
            throw new AuthenticationServiceException("内容类型不支持: " + request.getContentType());
        }
        LoginDTO loginDTO = httpMessageConverter.read(LoginDTO.class, servletServerHttpRequest);
        //封装，未认证
        RiceBallAuthenticationToken authRequest = new RiceBallAuthenticationToken(loginDTO);
        authRequest.setDetails(authenticationDetailsSource.buildDetails(request));
        RiceBallAuthenticationProvider provider = new RiceBallAuthenticationProvider();
        RiceBallAuthenticationManager authenticationManager = new RiceBallAuthenticationManager(provider);
        //通过authenticationManager去认证
        return authenticationManager.authenticate(authRequest);
    }
}
